package lib;

import java.io.Serializable;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;

public class VectorClock implements Serializable, Cloneable {

	/**
	 * 
	 */
	private static final long serialVersionUID = -8761765948522375160L;
	private HashMap<String, Integer> vector;

	public VectorClock() {
		this.vector = new HashMap<String, Integer>();
	}

	public HashMap<String, Integer> getVector() {
		return vector;
	}

	public int addOneTo(String processId) {
		if (!vector.containsKey(processId)) {
			vector.put(processId, 0);
		}
		int value = vector.get(processId) + 1;
		vector.put(processId, value);
		return value;
	}
	
	public void set(String processId, int value) {
		vector.put(processId, value);
	}

	public int get(String processId) {
		if (!vector.containsKey(processId)) {
			vector.put(processId, 0);
		}
		return vector.get(processId);
	}

	public Set<String> getProcessIds() {
		return vector.keySet();
	}

	public static VectorClock mergeClocks(VectorClock vc1, VectorClock vc2) {
		VectorClock merge = new VectorClock();
		Iterator<String> i1 = vc1.getProcessIds().iterator();
		Iterator<String> i2;
		String id1, id2;
		int val1, val2;

		while (i1.hasNext()) {
			i2 = vc2.getProcessIds().iterator();
			id1 = i1.next();
			while (i2.hasNext()) {
				id2 = i2.next();
				if (id1.equals(id2)) {
					val1 = vc1.get(id1);
					val2 = vc2.get(id2);
					merge.set(id1, Math.max(val1, val2));
				}
			}
		}

		return merge;
	}

	public String toString() {
		String result = "[";
		Iterator<String> it = vector.keySet().iterator();
		while (it.hasNext()) {
			result += vector.get(it.next());
			if (it.hasNext()) {
				result += ", ";
			}
		}
		return result + "]";
	}
	
	public Object Clone() {
		VectorClock vectorClock = null;
		try {
			vectorClock = (VectorClock) super.clone();
			vectorClock.vector = new HashMap<String, Integer>(vector);
		} catch (CloneNotSupportedException e) {
			//e.printStackTrace();
		}
		return vectorClock;
	}

}
